/**
 * Created by seeker910 on 13-12-31.
 */
Rsd.define('Rsd.common.Application', {
    extend:'Rsd.common.Object',
    requires:['Rsd.data.Plugin','Rsd.data.ModelSchema',"Rsd.common.EventList",'Rsd.data.Service','Rsd.data.Logger','Rsd.common.Lang'],
    xtype:'application',
    //应用ID ==>clientId
    appId:null,
    /**
     * appAuth 授权(暂不包含 appToken信息) 用于验证union app授权
     */
    authorization:null, 
    /**
     * request token ==>用户访问令牌
     * 应取消该字段，将其加密到authorization中
     */
    appToken:null,
    //标题
    appTitle: '',
    //名称
    appName: '',
    //源文件
    appFolder:'src', 
    //版本号
    appVersion:'0.0.0.0',
    //版本发布日期
    appDate:new Date().getTime(),
    //js 脚本代理服务器地址 ，设置该值后，所有js脚本请求 会被指向该地址，且请求格式为jsAgentHost/base64(path),且需要在代理服务上 先解析path内容 
    jsAgentHost:'',
    lang:'zh-cn',
    svg:null,
    /*api service*/
    //services:{},
    schemas:{},
    /**
     * 环境变量
     */
    globalVariables:{},
    //app启动时间
    startTime:0,
    // Hosts 服务已加载完毕
    isReady:false,
    isDemo: window.location.protocol  == 'file:',
    getSchemaListHandler:'',
    getSchemaHandler:'', 
    /**
     * @description 延时启动时长（毫秒）,一般用于等待框架加载
     */
    delay:100,
    /**
     * 提前加载svg资源
     */
    svgLoad:false,
    /**
     * 启用图表控件
     */
    useChart:false,
    //应用内 插件  
    plugins:[], 
    /**
     * {
     * //标题
     * text:'电商服务',
     * //名称
     * name:'biz',
     * async:true,//异步加载
     * //地址
     * url:'http://hermes.redmicro.cn/',
     * //服务端 状态探测地址
     * index:'dev/index',
     * routeList:'/dev/getroutetable',
     * controllers:[{name:'',path:''}]
     * isLoading:false//加载中
     * //是否使用ssl
     * useSSL:false
     * }
     */ 
    //appHosts:[]

    /**
     * @description 模板文件库 ,程序启动时，将模板加载到本地并编译后 存在 indexDB中
     * {
     *   name:'',path
     * }
     */
    templates:[],
    /**
     * 全局图片资源接口
     * {
     *  getAlbumList:"",//'global.merch.album.GetAlbumList'
        saveAlbum:"",//'global.merch.album.SaveAlbum'
        deleteAlbum:"",//'global.merch.album.DeleteAlbum'
        getImageList:""//'global.merch.image.GetImageList'
     * }
     */
    imageSelectorServices:null,
    /*
    * */
    constructor: function Application(config) {
        //debugger;
        this.apply(config);
        this.plugins = this.plugins || [];
        this.__plugin_mapping = this.__plugin_mapping || {};
    },
    /**
     * @description 启动程序
     * */
    run :function run() {
        var me = this;
        //console.trace('run');
        Rsd.create('Rsd.common.Lang',{}).load(me.lang);
        if(me.svgLoad)
        {
            var svgLoader = Rsd.create('Rsd.data.SvgLoader',{});
            svgLoader.load('redjs',Rsd.getRedjsHost() + "/resources/svg/icon.js");
            if(me.svg)
            {
                svgLoader.load('./resources/svg/' + me.svg+'.js?t=' + Rsd.timestamp);
            }
        }
         
        if (Rsd.validateBrowser() == false) {
            var error = '浏览器版本过低，请升级或选择其他浏览器。';
            Rsd.alert(error);
            document.title = error;
            return;
        }
        if(!Rsd.isEmpty(this.appTitle))
        {
            window.document.title =  this.appTitle;
        }

        //加载依赖项
        setTimeout(function () {

            var _obj;

            for (var c in me.requires) {

                if(!me.requires.hasOwnProperty(c))
                {
                    continue;
                }
                _obj = me.requires[c];
                var isJs = /(\.js)$/.test(_obj);
                if (isJs) {

                    Rsd.loadScriptFile(_obj);
                }
                else {
                    //console.log('application run',_obj);
                    Rsd.loadClass(_obj);
                }

            }
        },0);

        setTimeout(function () {
            //探测API是否可用
            me.testServerHost(function (data) {
                //console.trace('testServerHost');
                if(!data.success)
                {
                    Rsd.create('Rsd.zen.page.ErrorPage',{text:data.msg}).show(); 
                }
                else
                {
                    //延时启动程序
                    setTimeout(function(){
                        me.launch.call(me);
                    },me.delay||0);
                    
                }

            })

        },0);

        Rsd.debug('App is runing.');
    },
    /**
     * 应用重启
     */
    restart:function restart()
    {
        this.run();
    },
    /**
     * @description 加载应用插件
     * @param {*} plugin  插件路径 或 插件配置项
     * @param {*} callback 
     * @returns 
     */
    loadPlugin:function loadPlugin(plugin,callback)
    {  
        var app = this;
 
        if (Rsd.isString(plugin)) { 

            var _pluginPath = plugin;
            var _s = new Rsd.data.Store({
                proxy: {
                    url: _pluginPath + '/config.js',
                    method: 'get'
                }
            });

            _s.load({}, function (config) {

                if (config) {

                    if(!config.name)
                    { 
                        throw new Error('the name is must need in plugin config');
                    } 
                    config.path =  _pluginPath;//定位页面
                    app.loadPlugin(config,callback);
                }
            });

            return; 
        } 
        var pluginKey = plugin.name.toLowerCase();
        //是否已存在
        if (this.__plugin_mapping[pluginKey]) {

            if (callback) {
                callback(this.__plugin_mapping[pluginKey]);
            } 
            return;
        } 
        var _plugin = plugin;
        if(!(plugin instanceof Rsd.data.Plugin))
        {
            _plugin = new Rsd.data.Plugin(plugin);
        }
        
        app.plugins.push(_plugin);
        app.__plugin_mapping[pluginKey] = _plugin;

        if (callback) {
            callback(_plugin);
        }
         
        //console.log(plugin.name,plugin instanceof Rsd.data.Plugin); 
    },
    /**
     * 应用内插件
     */
    getPlugin:function getPlugin(name)
    { 
       return  this.__plugin_mapping && this.__plugin_mapping[name.toLowerCase()] ;
    },
    /**
    * 探测服务端 是否可用
    * */
    testServerHost:function testServerHost(callback) {

        if( Rsd.app.apiHosts == null || Rsd.app.apiHosts.length == 0)
        {
            Rsd.callFunction(callback,me,[{success:true}]);  
            return ;            
        }

        var me = this;
        me.isReady = false;  
        me.__is_callback = false;
        var _count = 0;
        
        var _fn = function()
        { 
            var host = this;
            
            if(Rsd.isEmpty(host.url))
            {   
                console.error('Host属性Url不存在',host);
                if(me.apiHosts.length == _count)
                { 
                    Rsd.callFunction(callback,me,[{success:true}]);  
                }   
                
                return;
            }

            var _testUrl = host.url + host.index||''; 
            host.testTimers++;
            var _method = 'GET';
            Rsd.debug('第'+ host.testTimers + '次:探测'+_method+'=>（url:'+ _testUrl +'）远程服务。');
           
            Rsd.httpRequest({ 
                    url:_testUrl,
                    method:_method,
                    error: null,
                    fail:function(data){
                        
                        Rsd.debug("----httpRequest fail-----",host,data);
                        Rsd.warn(host.url +'系统繁忙，稍后再试');
                        if(me.isReady)
                        {
                            return;
                        }
                        if(me.apiHosts.length == _count)
                        {  
                            Rsd.callFunction(callback,me,[{success:true}]);
                            me.__is_callback = true;
                        }
                        
                    }, 
                    complete:function()
                    {    
                        if(host.testTimers==1)
                        {
                            _count++;
                        }
                        if(!host.success)
                        {
                            if(host.testTimers < 5)
                            { 
                                setTimeout(function () {
                                    _fn.call(host);
                                },200*host.testTimers);
         
                            }
                            else
                            {
                                Rsd.warn(host.url +' 系统繁忙，稍后再试');
                            } 
                        }
                       
                        //console.error(_count,me.apiHosts.length,me.apiHosts.length == _count,host); 
                        
                        if(!me.isReady)
                        {  
                            me.isReady = me.apiHosts.filter(function(item){return item.async ==false;} ).length == me.apiHosts.filter(function(item){return item.async ==false && item.success;}).length;
                        }
         
                        if(me.isReady && !me.__is_callback)
                        {
                            Rsd.debug('>>>>>>>>>>is ready to start <<<<<<<<<<<<');
                            Rsd.callFunction(callback,me,[{success:true}]);
                            me.__is_callback = true;
                            return;
                        }
                       
                        if(me.apiHosts.length == _count && !me.__is_callback)
                        {  
                            Rsd.debug('>>>>>>>>>>is competed to start <<<<<<<<<<<<');
                            Rsd.callFunction(callback,me,[{success:true}]);
                            me.__is_callback = true;
                        }
                        
                    }
                },
                {},
                function(data){ 
                    host.success = true; 
            });
        }

        for(var i in Rsd.app.apiHosts)
        {
            var host = Rsd.app.apiHosts[i]; 
            host.testTimers = 0;
            (function(){
                var _host = this;
            
                setTimeout(function() {
                    _fn.call(_host); 
                }, 0);
            
            }).call(host);
            
        }    
        
      
    },
    /**
     * 设置环境变量,不区分大小写
     * @param {*} key 
     * @param {*} value 
     * @returns 
     */
    setGlobalVariable:function setGlobalVariable(key,value)
    {
        if(Rsd.isEmpty(key))
        {
            return;    
        }
        this.globalVariables[key.toLowerCase()] = value;
    },
    /**
     * 获取环境变量,不区分大小写
     * @param {*} key 
     */
    getGlobalVariable:function getGlobalVariable(key)
    {
        if(Rsd.isEmpty(key))
        {
            return "";    
        }
        return this.globalVariables[key.toLowerCase()] || '';
    }, 
    /**
    *
    *
    * */
    addService:function addService(key,config)
    {
        var _name = key.toLowerCase();
        var _group = _name.substr(0,_name.lastIndexOf('.'));
        var _method = _name.substr(_name.lastIndexOf('.')+1);

        this.services[_group].api[_method] = new Rsd.data.Service(config);
    },
    /**
     * @description Service 是否存在
     */
    containsService:function containsService(name)
    {
        if(Rsd.isEmpty(name))
            {
                throw new Error('param [name] is null when call  Application.getService method.');
            }
            var _name = name.toLowerCase();
            var _group = _name.substr(0,_name.lastIndexOf('.'));
            var _method = _name.substr(_name.lastIndexOf('.')+1);

            return Rsd.services[_group]&&Rsd.services[_group].api.hasOwnProperty(_method)&&Rsd.services[_group].api[_method]instanceof  Rsd.data.Service
    },
    /**
     * @description 获取当前服务环境中的服务
     * */
    getService: function getService(name){

        if(Rsd.isEmpty(name))
        {
            throw new Error('param [name] is null when call  Application.getService method.');
        }
        var _name = name.toLowerCase();
        var _group = _name.substr(0,_name.lastIndexOf('.'));
        var _method = _name.substr(_name.lastIndexOf('.')+1);


        var service = Rsd.services[_group];

        if(Rsd.isEmpty(service) )
        {
            var _error = '服务['+ name +']不存在,请先注册';
            alert(_error);
            console.error(_error);
            return;
        }

        //console.log(service);

        if(!service.api.hasOwnProperty(_method))
        {
            var _error = '服务['+ name +']不存在,请确认';
            alert(_error);
            console.error(_error);
            return null;
        }

        if(Rsd.isEmpty(service.api) && service.isLoading)
        {
            var _error = '服务['+ name +']正在加载，请稍后';
            alert(_error);
            console.error(_error);
            return;
        }
        
        var item = service.api[_method];

        if(item instanceof  Rsd.data.Service)
        {
            return item;
        }
        //
        return new Rsd.data.Service({
            key:_name,
            group:_group,
            parent : this,
            msg:msg,
            timeout:timeout,
            errorHandler :'',
            failureHandler : '',
            successHandler : '',
            progressHandler: '',
            ajaxType:'ajax',
            local:{method:'get',url:''},
            server:{
                url:item.Url,
                method:item.Method || 'POST',
                //contentType:'application/json',
                //dataType: 'json',
                async:true
            }

        });
    },

    /**
     * @description 服务未加载完成时，有两次各延时1秒的处理
     * @param {*} name 
     * @param {*} data 
     * @param {*} callback  请求成功（status==200）回调方法,且优先执行，执行返回true时,后续方法（success,failure）继续执行，返回false时，后续方法终止
     * @param {*} msg 
     * @param {*} timeout 
     */
    requestService:function requestService(name, data, callback,msg,timeout) {

        var _name = name;
        var _data = data;
        var _callback = callback;
        var _msg = msg||"正在处理，请稍后..."
        var _timeout = timeout;
        if(Rsd.isNumber(msg))
        {
            _timeout = msg;
        }
        if(Rsd.isString(timeout))
        {
            _msg = timeout;
        }
        Rsd.requestService(_name, _data, _callback,_msg,timeout);
    },

    /**
     * @description 展示表单
     * @param modeltype
     * @param formfields
     * @param record
     * @param title
     * @param buttons
     * @param readonly
     * @param parent
     *  
     * */
    showFormView:function showFormView(config,position) {

        var _config = config||{};
        

        if(!_config.modelType.startWith('Rsd.'))
        {
            _config.modelType = Rsd.app.assembelyName + '.' + _config.modelType ;
        }
        _config.parent = _config.parent ||this;
        _config.readonly = (_config.readonly==undefined?false:_config.readonly);
       
        this.getSchema(_config.modelType,function (schema) {
           
            config.modelSchema = schema; 
            var form = Rsd.create('Rsd.zen.dialog.BizFormDialog', config);

            if(position == 'left')
            {
                form.showDialogOnLeft().load();
                return;
            }
            
            if(position == 'right')
            {
                form.showDialogOnRight().load();
                return;
            }

            form.showDialog().load();

          });

    },
 
    /**
     * @description 以控制台的方式打开插件
     * @param {*} plugin  控件路径，一个插件可以被多个控制台实例使用，不同控制台有不同data
     * @param {*} data 控制台数据(插件 是一个静态数据，不包含data)
     * @param {*} config  控制台配置项
     * @returns 
     */
    showConsole : function showConsole(plugin,data,config){ 
          
        if (!Rsd.isString(plugin)) { 
            throw new Error('argument plugin is not string type.');
        } 
        var _p_path = plugin;

        var _c = config || {};
        if (Rsd.isString(config)) {
            _c = { title: config }
        }

        var _fn = function (_plugin) {
            //console.log(_plugin);
            var _config = Rsd.apply({
                width: '90%',
                height: '90%',
                title: _plugin.title || _plugin.text || '无标题',
                logo: _plugin.icon || _plugin.logo,
                plugin: _plugin,
                parent: _plugin,
                menu: _plugin.menu,
                data: data,
                top: _plugin.top || {},
                left: _plugin.left || {},
                style: {
                    top: '5%',
                    left: '5%',
                    opacity: 1,
                    boxShadow: '0px 20px 20px 17px #00000066',
                    backgroundColor: 'rgba(222, 222, 222, 1)'
                }
            }, _c);

            var _dialog = Rsd.create('Rsd.zen.dialog.ConsoleDialog', _config).showDialog();
          
            _dialog.load();
            if (_plugin.afterConsoleShown) {
                _plugin.afterConsoleShown(_dialog);
            } 
            return _dialog;
        }
  
        Rsd.app.loadPlugin(_p_path, function (_plugin) { 
            _fn(_plugin);
            //console.log('after show console -> plugin console is',_plugin.console);
        });

        return; 
    },
    /**
    * 表单 模型
     * */
    getSchemaList:function getSchemaList(callback) {

        if(!this.getSchemaListHandler)
        {
            Rsd.error('Application 类中未找到getSchemaListHandler的定义。');
            return;
        }
        return this.funApplyByIOC(this.getSchemaListHandler,[callback]);
    },
    /**
     * 表单 jsonSchema
     * @param {*} modelType 
     * @param {*} callback 
     */
    getJsonSchema:function getJsonSchema(modelType,callback) {
        console.error('需要将model schema 转化为jsonSchema');
    },
    /** 
    * 表单 model 
    * */
    getSchema:function getSchema(modelType,callback) {

        //debugger;
        if(!this.getSchemaHandler)
        {
            Rsd.error('Application 类中未找到getSchemaHandler的定义。');
            return;
        }
        return this.funApplyByIOC(this.getSchemaHandler,[modelType,callback])

    },
    /**
     * 
     * @param {*} modelType 
     * @param {*} value 
     * @param {*} callback 
     */
    getObjectByKey:function getObjectByKey(modelType,value,callback){
        
        if(callback)
        {
            callback(null);
        }

       if(value)
       { 
            console.error("获取["+modelType+"]对象失败，未在app文件中实现Rsd.app.getObjectByKey方法");  
       }
        
    },
    /**
     * 
     * @param {*} name 
     * @param {*} fn 
     * @param {boolean} once 一次性事件
     */
    on:function on(name,fn,once)
    {
        this.events.add(this,name.toLowerCase(),fn,once);
    },
    /**
     * 
     * @param {*} name 
     * @param {*} args 
     */
    fire:function fire(name,args)
    { 
        this.events.fire(this,name.toLowerCase(),args);
    },
    /**
     * 注销事件
     * @param {*} name 
     */
    off:function off(name)
    { 
        this.events.remove(this,name.toLowerCase());
    }
    
},function(type){

    var _eventsGetter = function () {
            
        if (this.__events == null) {
            this.__events = Rsd.create('Rsd.common.EventList', {parent:this});
        }
        return this.__events;
    };

    this.defineProperty(type,"events", _eventsGetter, null,true);
    //
    this.defineProperty(type,'appHosts',function(){return this.__appHost||[];},function(appHost){
        if(Rsd.isAarry(appHost))
        {
            this.__appHost = appHost; 
            return ;
        }
        if(Rsd.isString(appHost))
        {
            this.__appHost = [{url:appHost,async:true,useSSL:false,index:'',name:'biz',text:"业务"}]; 
            return ;
        }
        this.__appHost = [appHost];

    },false);
    //全局变量 重命名
    this.defineProperty(type,'var',function(){return this.__globalVariables||{};},function(data){
         
        this.__globalVariables = data;

    },false);
//

});